<!--
使用antd原生Form生成 详细用法参考ant-design-vue Form组件文档
vscode默认配置文件会自动格式化/移除未使用依赖
-->
<script setup lang="ts">
import { cloneDeep, pick } from 'lodash-es';
import { computed, h, reactive, ref, watch } from 'vue';
import { Form, message, Modal, Input, Button, Textarea, Select, SelectOption, Row, Col, FormItem, InputNumber } from 'ant-design-vue';
import type { RuleObject } from 'ant-design-vue/es/form';
import { useVbenDrawer } from '@vben/common-ui';
import { useBeforeCloseDiff } from '#/utils/popup';
import { $t } from '@vben/locales';
import { officeCostAdd, officeCostInfo, officeCostUpdate, officeCostSubmit, officeCostApprove, officeCostInvalidate, officeCostList } from '#/api/trade/officeCost';
import type { OfficeCostForm } from '#/api/trade/officeCost/model';
import { APPROVE_STATUS } from '../constants';
import { ImageUpload, FileUpload } from '#/components/upload';
import { generateOfficeCostNo } from '#/utils/generator';

const emit = defineEmits<{ reload: [] }>();

const isUpdate = ref(false);
const title = computed(() => {
  return isUpdate.value ? $t('pages.common.edit') : $t('pages.common.add');
});

/**
 * 定义默认值 用于reset
 */
const defaultValues: Partial<OfficeCostForm> = {
  id: undefined,
  deptId: undefined,
  no: undefined,
  totalAmount: undefined,
  attachments: undefined,
  status: APPROVE_STATUS.DRAFT,
  details: [{ name: '', amount: undefined }],
  remark: undefined,
  rejectReason: undefined,
}

/**
 * 表单数据ref
 */
const formData = ref(defaultValues);

// 附件列表，用于FileUpload组件的双向绑定
const attachmentsList = ref<string[]>([]);

// 处理附件变化
const handleAttachmentsChange = () => {
  // 将数组转换为逗号分割的字符串
  formData.value.attachments = attachmentsList.value.length > 0 
    ? attachmentsList.value.join(',') 
    : undefined;
};

// 监听formData.attachments变化，同步到attachmentsList
watch(
  () => formData.value.attachments,
  (newAttachments) => {
    if (newAttachments && typeof newAttachments === 'string') {
      // 将逗号分割的字符串转换为数组
      attachmentsList.value = newAttachments.split(',').filter(id => id.trim());
    } else {
      attachmentsList.value = [];
    }
  },
  { immediate: true }
);

type AntdFormRules<T> = Partial<Record<keyof T, RuleObject[]>> & {
  [key: string]: RuleObject[];
};
/**
 * 表单校验规则
 */
const formRules = ref<AntdFormRules<OfficeCostForm>>({
    details: [
      { required: true, message: "费用明细不能为空" },
      { 
        validator: (rule: any, value: any) => {
          if (!value || value.length === 0) {
            return Promise.reject('至少需要一条费用明细');
          }
          return Promise.resolve();
        }
      }
    ],
});

/**
 * useForm解构出表单方法
 */
const { validate, validateInfos, resetFields } = Form.useForm(
  formData,
  formRules,
);

function customFormValueGetter() {
  return JSON.stringify(formData.value);
}

const { onBeforeClose, markInitialized, resetInitialized } = useBeforeCloseDiff(
  {
    initializedGetter: customFormValueGetter,
    currentGetter: customFormValueGetter,
  },
);

const [BasicDrawer, drawerApi] = useVbenDrawer({
  class: 'w-[800px]',
  onBeforeClose,
  onClosed: handleClosed,
  onConfirm: handleConfirm,
  onOpenChange: async (isOpen) => {
    if (!isOpen) {
      return null;
    }
    drawerApi.drawerLoading(true);

    const { id } = drawerApi.getData() as { id?: number | string };
    isUpdate.value = !!id;

    if (isUpdate.value && id) {
      const record = await officeCostInfo(id);
      // 只赋值存在的字段
      const filterRecord = pick(record, Object.keys(defaultValues));
      formData.value = filterRecord;
      // 确保至少有一条明细
      if (!formData.value.details || formData.value.details.length === 0) {
        formData.value.details = [{ name: '', amount: undefined }];
      }
      // 重新计算总金额
      calculateTotalAmount();
    }
    await markInitialized();

    drawerApi.drawerLoading(false);
  },
});

async function handleConfirm() {
  try {
    drawerApi.lock(true);
    await validate();
    
    // 如果费用单号为空，自动生成
    if (!formData.value.no || formData.value.no.trim() === '') {
      formData.value.no = generateOfficeCostNo();
    }
    
    // 可能会做数据处理 使用cloneDeep深拷贝
    const data = cloneDeep(formData.value);
    await (isUpdate.value ? officeCostUpdate(data) : officeCostAdd(data));
    resetInitialized();
    emit('reload');
    drawerApi.close();
  } catch (error) {
    console.error(error);
  } finally {
    drawerApi.lock(false);
  }
}

async function handleClosed() {
  formData.value = cloneDeep(defaultValues);
  resetFields();
  resetInitialized();
}

// 提交
async function handleSubmit() {
  try {
    drawerApi.lock(true);
    await validate();
    
    // 如果费用单号为空，自动生成
    if (!formData.value.no || formData.value.no.trim() === '') {
      formData.value.no = generateOfficeCostNo();
    }
    
    const data = cloneDeep(formData.value);
    await (isUpdate.value ? officeCostUpdate(data) : officeCostAdd(data));
    //根据单号查询
    if(!isUpdate.value){
      const currentCost = await officeCostList({
            no: data.no,
          });
          if (currentCost.total > 0) {
            data.id = currentCost.rows[0]?.id;
          }
    }
    
    await officeCostSubmit([data.id!]);
    message.success('重新提交成功');
    resetInitialized();
    emit('reload');
    drawerApi.close();
  } catch (error) {
    console.error('重新提交失败', error);
  } finally {
    drawerApi.lock(false);
  }
}

// 审核通过
async function handleApprove() {
  Modal.confirm({
    title: '确认审核通过？',
    content: '审核通过后将无法修改，请确认操作',
    onOk: async () => {
      try {
        await officeCostApprove(formData.value.id!, true, undefined);
        message.success('审核通过成功');
        emit('reload');
        drawerApi.close();
      } catch (error) {
        console.error('审核通过失败', error);
      }
    },
  });
}

// 驳回
async function handleReject() {
  Modal.confirm({
    title: '请输入驳回原因',
    content: h(Input.TextArea, {
      placeholder: '请输入驳回原因',
      rows: 4,
      onInput: (e: Event) => {
        rejectReason.value = (e.target as HTMLTextAreaElement).value;
      },
    }),
    onOk: async () => {
      if (!rejectReason.value.trim()) {
        message.warning('请输入驳回原因');
        return Promise.reject();
      }
      try {
        await officeCostApprove(formData.value.id!, false, rejectReason.value);
        message.success('驳回成功');
        emit('reload');
        drawerApi.close();
      } catch (error) {
        console.error('驳回失败', error);
      }
    },
  });
}

// 作废
async function handleCancel() {
  Modal.confirm({
    title: '确认作废？',
    content: '作废后将无法恢复，请确认操作',
    onOk: async () => {
      try {
        await officeCostInvalidate(formData.value.id!);
        message.success('作废成功');
        emit('reload');
        drawerApi.close();
      } catch (error) {
        console.error('作废失败', error);
      }
    },
  });
}

const rejectReason = ref('');

// 驳回原因是否可见
const showRejectReason = computed(() => {
  return formData.value.rejectReason && formData.value.rejectReason.trim() !== '';
});

// 表单是否禁用 - 只有待提交、已驳回状态下才可以输入
const isFormDisabled = computed(() => {
  return formData.value.status !== null && formData.value.status !== APPROVE_STATUS.DRAFT && formData.value.status !== APPROVE_STATUS.REJECTED;
});

// 添加费用明细
function addDetail() {
  formData.value.details.push({
    name: '',
    amount: undefined,
  });
}

// 删除费用明细
function removeDetail(index: number) {
  if (formData.value.details.length > 1) {
    formData.value.details.splice(index, 1);
    calculateTotalAmount();
  }
}

// 计算费用合计
function calculateTotalAmount() {
  const total = formData.value.details.reduce((sum, detail) => {
    return sum + (detail.amount || 0);
  }, 0);
  formData.value.totalAmount = total;
}
</script>

<template>
  <BasicDrawer :title="title">
    <template #footer>
      <div class="flex justify-between">
        <!-- 操作按钮 -->
        <div class="flex space-x-3">
          <Button v-if="formData.status === APPROVE_STATUS.DRAFT || formData.status === APPROVE_STATUS.REJECTED" type="primary" @click="handleSubmit">提交审核</Button>
          <Button v-if="formData.status === APPROVE_STATUS.WAITING" type="primary" @click="handleApprove">通过</Button>
          <Button v-if="formData.status === APPROVE_STATUS.WAITING" danger @click="handleReject">驳回</Button>
          <Button v-if="formData.status === APPROVE_STATUS.DRAFT ||  formData.status === APPROVE_STATUS.REJECTED" danger @click="handleCancel">作废</Button>
          <Button  v-if="!formData.status || formData.status === APPROVE_STATUS.DRAFT || formData.status === APPROVE_STATUS.REJECTED" type="primary" @click="handleConfirm">仅保存</Button>
          <Button @click="drawerApi.close()">返回</Button>
        </div>
      </div>
    </template>
    <Form
       :label-col="{ span: 6 }"
       :wrapper-col="{ span: 18 }"
       :model="formData"
       :rules="formRules"
     >
       <Row :gutter="16">
         <Col :span="12">
           <FormItem
             label="费用单号"
             name="no"
             v-bind="validateInfos.no"
           >
             <Input
               v-model:value="formData.no"
               placeholder="请输入费用单号，忽略则自动生成"
               :disabled="isFormDisabled"
             />
           </FormItem>
         </Col>
       </Row>
       <!-- 费用明细 -->
       <Row :gutter="16">
         <Col :span="24">
          <div class="space-y-3">
               <!-- 明细列表 -->
               <div v-for="(detail, index) in formData.details" :key="index" class="border border-gray-200 rounded p-3">
                 <Row :gutter="16" align="middle">
                   <Col :span="10">
                     <FormItem
                       :label="`支出说明`"
                       :name="['details', index, 'name']"
                       :rules="[{ required: true, message: '支出说明不能为空' }]"
                     >
                       <Input
                         v-model:value="detail.name"
                         placeholder="请输入支出说明"
                         :disabled="isFormDisabled"
                       />
                     </FormItem>
                   </Col>
                   <Col :span="10">
                     <FormItem
                       :label="`金额`"
                       :name="['details', index, 'amount']"
                       :rules="[{ required: true, message: '金额不能为空' }]"
                     >
                       <InputNumber
                         v-model:value="detail.amount"
                         placeholder="请输入金额"
                         :min="0"
                         :precision="2"
                         :disabled="isFormDisabled"
                         style="width: 100%"
                         @change="calculateTotalAmount"
                       />
                     </FormItem>
                   </Col>
                   <Col :span="4">
                     <Button
                       v-if="!isFormDisabled"
                       type="text"
                       danger
                       @click="removeDetail(index)"
                       :disabled="formData.details.length <= 1"
                     >
                       删除
                     </Button>
                   </Col>
                 </Row>
               </div>
               
               <!-- 添加按钮 -->
               <div class="flex justify-center">
                 <Button
                   v-if="!isFormDisabled"
                   type="dashed"
                   @click="addDetail"
                   style="width: 50%"
                   class="border-2 border-dashed hover:border-solid border-c mb-5"
                 >
                   + 添加费用明细
                 </Button>
               </div>
             </div>
         </Col>
       </Row>
       
       <!-- 费用合计 -->
       <Row :gutter="16">
         <Col :span="12">
           <FormItem
             label="费用合计"
             name="totalAmount"
             v-bind="validateInfos.totalAmount"
           >
             <InputNumber
               v-model:value="formData.totalAmount"
               placeholder="自动计算"
               :min="0"
               :precision="2"
               disabled
               style="width: 100%"
             />
           </FormItem>
         </Col>
       </Row>

       <Row :gutter="16">
          <Col :span="24">
            <FormItem label="备注" :label-col="{ span: 3 }">
              <Textarea
                v-model:value="formData.remark"
                placeholder="请输入备注"
              />
            </FormItem>
          </Col>
        </Row>
       <Row :gutter="16">
         <Col :span="12">
           <FormItem
             label="费用附件"
             name="attachments"
             v-bind="validateInfos.attachments"
           >
             <FileUpload
               :max-count="10"
               v-model:value="attachmentsList"
               @change="handleAttachmentsChange"
               accept=".jpg,.jpeg,.png,.gif,.webp,.xlsx,.csv,.docx,.pdf"
               :disabled="isFormDisabled"
             />
           </FormItem>
         </Col>
       </Row>
       <!-- 驳回原因字段，仅在有驳回原因时显示 -->
       <Row v-if="showRejectReason">
         <Col :span="24">
           <FormItem
             label="驳回原因"
             :label-col="{ span: 3 }"
             :wrapper-col="{ span: 21 }"
           >
             <Textarea
               v-model:value="formData.rejectReason"
               :rows="3"
               placeholder="驳回原因"
               disabled
               :maxlength="200"
               show-count
             />
           </FormItem>
         </Col>
       </Row>
     </Form>
  </BasicDrawer>
</template>

